package com.urbanski.util;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * An assortment of utility methods for arrays
 * 
 * @author Mike Urbanski
 * 
 */
public class ArrayUtils
{
	/**
	 * Returns a map in which each item in the keys array maps to the element in
	 * the values array with the same index.
	 * 
	 * Does not account for duplicate keys. If the keys array contains duplicate
	 * equal elements, the last occurring duplicate (and its associated element
	 * in values) will be used.
	 * 
	 * For example, given the following arrays:
	 * 
	 * Keys Values ---- ------ 10 "ABC" 11 "DEF" 20 "QWE" 10 "XYZ"
	 * 
	 * This method would return the following map:
	 * 
	 * 10 -> "XYZ" 11 -> "DEF" 20 -> "QWE"
	 * 
	 * If the arrays do not have the same length, then elements will be mapped
	 * up to the last index of the smaller array.
	 * 
	 * @param keys
	 *            the elements that will appear as keys in the resulting map
	 * @param values
	 *            the elements that will appear as values in the resulting map
	 * @return a mapping the elements in keys to the elements in values
	 * @throws NullPointerException
	 *             if either array is null
	 */
	public static <E, F> Map<E, F> asMap(E[] keys, F[] values)
	{
		int length = Math.min(keys.length, values.length);

		Map<E, F> map = new LinkedHashMap<E, F>();

		for (int i = 0; i < length; i++)
		{
			map.put(keys[i], values[i]);
		}

		return map;
	}

	/**
	 * Returns a map in which each even-numbered item in the keys array maps to
	 * the next element (index + 1) in the array. If keys.length is odd, then
	 * the last element will map to null .
	 * 
	 * Does not account for duplicate keys. If the keys array contains duplicate
	 * equal elements (at even indexes), the last occurring duplicate (and its
	 * associated value) will be used.
	 * 
	 * For example, given the following array:
	 * 
	 * {10, "ABC", 11, "DEF", 20, "QWE", 10, "XYZ"}
	 * 
	 * This method would return the following map:
	 * 
	 * 10 -> "XYZ" 11 -> "DEF" 20 -> "QWE"
	 * 
	 * @param keys
	 *            the elements and values of the map
	 * @return a mapping the elements in keys to the elements in values
	 * @throws IllegalArgumentException
	 *             if the lengths of the arrays are not equal
	 * @throws NullPointerException
	 *             if either array is null
	 */
	public static <E> Map<E, E> asMap(E[] keys)
	{
		Map<E, E> map = new LinkedHashMap<E, E>();

		for (int i = 0; i < keys.length - 1; i += 2)
		{
			map.put(keys[i], keys[i + 1]);
		}

		if (keys.length % 2 == 1)
		{
			map.put(keys[keys.length - 1], null);
		}

		return map;
	}

	/**
	 * Prints out the array on one line with default delimiters (,) surrouned by
	 * square brackets ([ and ]) with no newline at end. This printing is
	 * analogous to the toString method of Collection classes.
	 * 
	 * @param arr
	 *            the array to print
	 */
	public static <E> void printArray(E[] arr)
	{
		printArray(arr, "[", "]", ", ", false);
	}

	/**
	 * Prints out the array on one line with the specified left and right
	 * surrounding characters (such as [ and ]) and delimiter with no newline at
	 * end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param left
	 *            the left surrounding string
	 * @param right
	 *            the right surrounding string
	 * @param delim
	 *            delimiter between elements
	 */
	public static <E> void printArray(E[] arr, String left, String right,
			String delim)
	{
		printArray(arr, left, right, delim, false);
	}

	/**
	 * Prints out the array on one line with default delimiters (,) surrouned by
	 * square brackets ([ and ]) with optional newline at end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param newline
	 *            whether to print a newline character at the end of the line
	 */
	public static <E> void printArray(E[] arr, boolean newline)
	{
		printArray(arr, "[", "]", ", ", newline);
	}

	/**
	 * Prints out the array on one line with the specified left and right
	 * surrounding characters (such as [ and ]) and delimiter with optional
	 * newline at end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param left
	 *            the left surrounding string
	 * @param right
	 *            the right surrounding string
	 * @param delim
	 *            delimiter between elements
	 * @param newline
	 *            whether to print a newline character at the end of the line
	 */
	public static <E> void printArray(E[] arr, String left, String right,
			String delim, boolean newline)
	{
		System.out.print(left);
		for (int i = 0; i < arr.length; i++)
		{
			System.out.print(arr[i]);
			if (i < arr.length - 1)
				System.out.print(delim);
		}
		System.out.print(right);
		if (newline)
			System.out.println();
	}

	/**
	 * Prints each element in the array on its own line, and end with a newline
	 * character
	 * 
	 * @param arr
	 *            the array to print
	 */
	public static <E> void printlnArray(E[] arr)
	{
		printlnArray(arr, true);
	}

	/**
	 * Prints each element in the array on its own line, optionally ending with
	 * a newline character
	 * 
	 * @param arr
	 *            the array to print
	 * @param newline
	 *            whether to print a newline after the last element
	 */
	public static <E> void printlnArray(E[] arr, boolean newline)
	{
		if (newline)
		{
			for (E e : arr)
			{
				System.out.println(e);
			}
		}
		else
		{
			for (int i = 0; i < arr.length; i++)
			{
				if (i < arr.length - 1)
					System.out.println(arr[i]);
				else
					System.out.print(arr[i]);
			}
		}
	}

	/**
	 * Adds all elements from the specified array to the specified Collection
	 * 
	 * @param c
	 *            the array to add to the Collection
	 * @param arr
	 *            the Collection to which to add the array
	 */
	public static <E> void addAll(Collection<? super E> c, E[] arr)
	{
		for (E e : arr)
		{
			c.add(e);
		}
	}
	
	/**
	 * Prints out the array on one line with default delimiters (,) surrouned by
	 * square brackets ([ and ]) with no newline at end. This printing is
	 * analogous to the toString method of Collection classes.
	 * 
	 * @param arr
	 *            the array to print
	 */
	public static void printArray(int[] arr)
	{
		printArray(arr, "[", "]", ", ", false);
	}

	/**
	 * Prints out the array on one line with the specified left and right
	 * surrounding characters (such as [ and ]) and delimiter with no newline at
	 * end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param left
	 *            the left surrounding string
	 * @param right
	 *            the right surrounding string
	 * @param delim
	 *            delimiter between elements
	 */
	public static void printArray(int[] arr, String left, String right,
			String delim)
	{
		printArray(arr, left, right, delim, false);
	}

	/**
	 * Prints out the array on one line with default delimiters (,) surrouned by
	 * square brackets ([ and ]) with optional newline at end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param newline
	 *            whether to print a newline character at the end of the line
	 */
	public static void printArray(int[] arr, boolean newline)
	{
		printArray(arr, "[", "]", ", ", newline);
	}

	/**
	 * Prints out the array on one line with the specified left and right
	 * surrounding characters (such as [ and ]) and delimiter with optional
	 * newline at end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param left
	 *            the left surrounding string
	 * @param right
	 *            the right surrounding string
	 * @param delim
	 *            delimiter between elements
	 * @param newline
	 *            whether to print a newline character at the end of the line
	 */
	public static void printArray(int[] arr, String left, String right,
			String delim, boolean newline)
	{
		System.out.print(left);
		for (int i = 0; i < arr.length; i++)
		{
			System.out.print(arr[i]);
			if (i < arr.length - 1)
				System.out.print(delim);
		}
		System.out.print(right);
		if (newline)
			System.out.println();
	}

	/**
	 * Prints each element in the array on its own line, and end with a newline
	 * character
	 * 
	 * @param arr
	 *            the array to print
	 */
	public static void printlnArray(int[] arr)
	{
		printlnArray(arr, true);
	}

	/**
	 * Prints each element in the array on its own line, optionally ending with
	 * a newline character
	 * 
	 * @param arr
	 *            the array to print
	 * @param newline
	 *            whether to print a newline after the last element
	 */
	public static void printlnArray(int[] arr, boolean newline)
	{
		if (newline)
		{
			for (int e : arr)
			{
				System.out.println(e);
			}
		}
		else
		{
			for (int i = 0; i < arr.length; i++)
			{
				if (i < arr.length - 1)
					System.out.println(arr[i]);
				else
					System.out.print(arr[i]);
			}
		}
	}
	
	/**
	 * Prints out the array on one line with default delimiters (,) surrouned by
	 * square brackets ([ and ]) with no newline at end. This printing is
	 * analogous to the toString method of Collection classes.
	 * 
	 * @param arr
	 *            the array to print
	 */
	public static void printArray(long[] arr)
	{
		printArray(arr, "[", "]", ", ", false);
	}

	/**
	 * Prints out the array on one line with the specified left and right
	 * surrounding characters (such as [ and ]) and delimiter with no newline at
	 * end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param left
	 *            the left surrounding string
	 * @param right
	 *            the right surrounding string
	 * @param delim
	 *            delimiter between elements
	 */
	public static void printArray(long[] arr, String left, String right,
			String delim)
	{
		printArray(arr, left, right, delim, false);
	}

	/**
	 * Prints out the array on one line with default delimiters (,) surrouned by
	 * square brackets ([ and ]) with optional newline at end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param newline
	 *            whether to print a newline character at the end of the line
	 */
	public static void printArray(long[] arr, boolean newline)
	{
		printArray(arr, "[", "]", ", ", newline);
	}

	/**
	 * Prints out the array on one line with the specified left and right
	 * surrounding characters (such as [ and ]) and delimiter with optional
	 * newline at end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param left
	 *            the left surrounding string
	 * @param right
	 *            the right surrounding string
	 * @param delim
	 *            delimiter between elements
	 * @param newline
	 *            whether to print a newline character at the end of the line
	 */
	public static void printArray(long[] arr, String left, String right,
			String delim, boolean newline)
	{
		System.out.print(left);
		for (int i = 0; i < arr.length; i++)
		{
			System.out.print(arr[i]);
			if (i < arr.length - 1)
				System.out.print(delim);
		}
		System.out.print(right);
		if (newline)
			System.out.println();
	}

	/**
	 * Prints each element in the array on its own line, and end with a newline
	 * character
	 * 
	 * @param arr
	 *            the array to print
	 */
	public static void printlnArray(long[] arr)
	{
		printlnArray(arr, true);
	}

	/**
	 * Prints each element in the array on its own line, optionally ending with
	 * a newline character
	 * 
	 * @param arr
	 *            the array to print
	 * @param newline
	 *            whether to print a newline after the last element
	 */
	public static void printlnArray(long[] arr, boolean newline)
	{
		if (newline)
		{
			for (long e : arr)
			{
				System.out.println(e);
			}
		}
		else
		{
			for (int i = 0; i < arr.length; i++)
			{
				if (i < arr.length - 1)
					System.out.println(arr[i]);
				else
					System.out.print(arr[i]);
			}
		}
	}
	
	/**
	 * Prints out the array on one line with default delimiters (,) surrouned by
	 * square brackets ([ and ]) with no newline at end. This printing is
	 * analogous to the toString method of Collection classes.
	 * 
	 * @param arr
	 *            the array to print
	 */
	public static void printArray(float[] arr)
	{
		printArray(arr, "[", "]", ", ", false);
	}

	/**
	 * Prints out the array on one line with the specified left and right
	 * surrounding characters (such as [ and ]) and delimiter with no newline at
	 * end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param left
	 *            the left surrounding string
	 * @param right
	 *            the right surrounding string
	 * @param delim
	 *            delimiter between elements
	 */
	public static void printArray(float[] arr, String left, String right,
			String delim)
	{
		printArray(arr, left, right, delim, false);
	}

	/**
	 * Prints out the array on one line with default delimiters (,) surrouned by
	 * square brackets ([ and ]) with optional newline at end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param newline
	 *            whether to print a newline character at the end of the line
	 */
	public static void printArray(float[] arr, boolean newline)
	{
		printArray(arr, "[", "]", ", ", newline);
	}

	/**
	 * Prints out the array on one line with the specified left and right
	 * surrounding characters (such as [ and ]) and delimiter with optional
	 * newline at end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param left
	 *            the left surrounding string
	 * @param right
	 *            the right surrounding string
	 * @param delim
	 *            delimiter between elements
	 * @param newline
	 *            whether to print a newline character at the end of the line
	 */
	public static void printArray(float[] arr, String left, String right,
			String delim, boolean newline)
	{
		System.out.print(left);
		for (int i = 0; i < arr.length; i++)
		{
			System.out.print(arr[i]);
			if (i < arr.length - 1)
				System.out.print(delim);
		}
		System.out.print(right);
		if (newline)
			System.out.println();
	}

	/**
	 * Prints each element in the array on its own line, and end with a newline
	 * character
	 * 
	 * @param arr
	 *            the array to print
	 */
	public static void printlnArray(float[] arr)
	{
		printlnArray(arr, true);
	}

	/**
	 * Prints each element in the array on its own line, optionally ending with
	 * a newline character
	 * 
	 * @param arr
	 *            the array to print
	 * @param newline
	 *            whether to print a newline after the last element
	 */
	public static void printlnArray(float[] arr, boolean newline)
	{
		if (newline)
		{
			for (float e : arr)
			{
				System.out.println(e);
			}
		}
		else
		{
			for (int i = 0; i < arr.length; i++)
			{
				if (i < arr.length - 1)
					System.out.println(arr[i]);
				else
					System.out.print(arr[i]);
			}
		}
	}
	
	/**
	 * Prints out the array on one line with default delimiters (,) surrouned by
	 * square brackets ([ and ]) with no newline at end. This printing is
	 * analogous to the toString method of Collection classes.
	 * 
	 * @param arr
	 *            the array to print
	 */
	public static void printArray(byte[] arr)
	{
		printArray(arr, "[", "]", ", ", false);
	}

	/**
	 * Prints out the array on one line with the specified left and right
	 * surrounding characters (such as [ and ]) and delimiter with no newline at
	 * end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param left
	 *            the left surrounding string
	 * @param right
	 *            the right surrounding string
	 * @param delim
	 *            delimiter between elements
	 */
	public static void printArray(byte[] arr, String left, String right,
			String delim)
	{
		printArray(arr, left, right, delim, false);
	}

	/**
	 * Prints out the array on one line with default delimiters (,) surrouned by
	 * square brackets ([ and ]) with optional newline at end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param newline
	 *            whether to print a newline character at the end of the line
	 */
	public static void printArray(byte[] arr, boolean newline)
	{
		printArray(arr, "[", "]", ", ", newline);
	}

	/**
	 * Prints out the array on one line with the specified left and right
	 * surrounding characters (such as [ and ]) and delimiter with optional
	 * newline at end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param left
	 *            the left surrounding string
	 * @param right
	 *            the right surrounding string
	 * @param delim
	 *            delimiter between elements
	 * @param newline
	 *            whether to print a newline character at the end of the line
	 */
	public static void printArray(byte[] arr, String left, String right,
			String delim, boolean newline)
	{
		System.out.print(left);
		for (int i = 0; i < arr.length; i++)
		{
			System.out.print(arr[i]);
			if (i < arr.length - 1)
				System.out.print(delim);
		}
		System.out.print(right);
		if (newline)
			System.out.println();
	}

	/**
	 * Prints each element in the array on its own line, and end with a newline
	 * character
	 * 
	 * @param arr
	 *            the array to print
	 */
	public static void printlnArray(byte[] arr)
	{
		printlnArray(arr, true);
	}

	/**
	 * Prints each element in the array on its own line, optionally ending with
	 * a newline character
	 * 
	 * @param arr
	 *            the array to print
	 * @param newline
	 *            whether to print a newline after the last element
	 */
	public static void printlnArray(byte[] arr, boolean newline)
	{
		if (newline)
		{
			for (byte e : arr)
			{
				System.out.println(e);
			}
		}
		else
		{
			for (int i = 0; i < arr.length; i++)
			{
				if (i < arr.length - 1)
					System.out.println(arr[i]);
				else
					System.out.print(arr[i]);
			}
		}
	}
	
	/**
	 * Prints out the array on one line with default delimiters (,) surrouned by
	 * square brackets ([ and ]) with no newline at end. This printing is
	 * analogous to the toString method of Collection classes.
	 * 
	 * @param arr
	 *            the array to print
	 */
	public static void printArray(short[] arr)
	{
		printArray(arr, "[", "]", ", ", false);
	}

	/**
	 * Prints out the array on one line with the specified left and right
	 * surrounding characters (such as [ and ]) and delimiter with no newline at
	 * end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param left
	 *            the left surrounding string
	 * @param right
	 *            the right surrounding string
	 * @param delim
	 *            delimiter between elements
	 */
	public static void printArray(short[] arr, String left, String right,
			String delim)
	{
		printArray(arr, left, right, delim, false);
	}

	/**
	 * Prints out the array on one line with default delimiters (,) surrouned by
	 * square brackets ([ and ]) with optional newline at end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param newline
	 *            whether to print a newline character at the end of the line
	 */
	public static void printArray(short[] arr, boolean newline)
	{
		printArray(arr, "[", "]", ", ", newline);
	}

	/**
	 * Prints out the array on one line with the specified left and right
	 * surrounding characters (such as [ and ]) and delimiter with optional
	 * newline at end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param left
	 *            the left surrounding string
	 * @param right
	 *            the right surrounding string
	 * @param delim
	 *            delimiter between elements
	 * @param newline
	 *            whether to print a newline character at the end of the line
	 */
	public static void printArray(short[] arr, String left, String right,
			String delim, boolean newline)
	{
		System.out.print(left);
		for (int i = 0; i < arr.length; i++)
		{
			System.out.print(arr[i]);
			if (i < arr.length - 1)
				System.out.print(delim);
		}
		System.out.print(right);
		if (newline)
			System.out.println();
	}

	/**
	 * Prints each element in the array on its own line, and end with a newline
	 * character
	 * 
	 * @param arr
	 *            the array to print
	 */
	public static void printlnArray(short[] arr)
	{
		printlnArray(arr, true);
	}

	/**
	 * Prints each element in the array on its own line, optionally ending with
	 * a newline character
	 * 
	 * @param arr
	 *            the array to print
	 * @param newline
	 *            whether to print a newline after the last element
	 */
	public static void printlnArray(short[] arr, boolean newline)
	{
		if (newline)
		{
			for (short e : arr)
			{
				System.out.println(e);
			}
		}
		else
		{
			for (int i = 0; i < arr.length; i++)
			{
				if (i < arr.length - 1)
					System.out.println(arr[i]);
				else
					System.out.print(arr[i]);
			}
		}
	}
	
	/**
	 * Prints out the array on one line with default delimiters (,) surrouned by
	 * square brackets ([ and ]) with no newline at end. This printing is
	 * analogous to the toString method of Collection classes.
	 * 
	 * @param arr
	 *            the array to print
	 */
	public static void printArray(double[] arr)
	{
		printArray(arr, "[", "]", ", ", false);
	}

	/**
	 * Prints out the array on one line with the specified left and right
	 * surrounding characters (such as [ and ]) and delimiter with no newline at
	 * end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param left
	 *            the left surrounding string
	 * @param right
	 *            the right surrounding string
	 * @param delim
	 *            delimiter between elements
	 */
	public static void printArray(double[] arr, String left, String right,
			String delim)
	{
		printArray(arr, left, right, delim, false);
	}

	/**
	 * Prints out the array on one line with default delimiters (,) surrouned by
	 * square brackets ([ and ]) with optional newline at end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param newline
	 *            whether to print a newline character at the end of the line
	 */
	public static void printArray(double[] arr, boolean newline)
	{
		printArray(arr, "[", "]", ", ", newline);
	}

	/**
	 * Prints out the array on one line with the specified left and right
	 * surrounding characters (such as [ and ]) and delimiter with optional
	 * newline at end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param left
	 *            the left surrounding string
	 * @param right
	 *            the right surrounding string
	 * @param delim
	 *            delimiter between elements
	 * @param newline
	 *            whether to print a newline character at the end of the line
	 */
	public static void printArray(double[] arr, String left, String right,
			String delim, boolean newline)
	{
		System.out.print(left);
		for (int i = 0; i < arr.length; i++)
		{
			System.out.print(arr[i]);
			if (i < arr.length - 1)
				System.out.print(delim);
		}
		System.out.print(right);
		if (newline)
			System.out.println();
	}

	/**
	 * Prints each element in the array on its own line, and end with a newline
	 * character
	 * 
	 * @param arr
	 *            the array to print
	 */
	public static void printlnArray(double[] arr)
	{
		printlnArray(arr, true);
	}

	/**
	 * Prints each element in the array on its own line, optionally ending with
	 * a newline character
	 * 
	 * @param arr
	 *            the array to print
	 * @param newline
	 *            whether to print a newline after the last element
	 */
	public static void printlnArray(double[] arr, boolean newline)
	{
		if (newline)
		{
			for (double e : arr)
			{
				System.out.println(e);
			}
		}
		else
		{
			for (int i = 0; i < arr.length; i++)
			{
				if (i < arr.length - 1)
					System.out.println(arr[i]);
				else
					System.out.print(arr[i]);
			}
		}
	}
	
	/**
	 * Prints out the array on one line with default delimiters (,) surrouned by
	 * square brackets ([ and ]) with no newline at end. This printing is
	 * analogous to the toString method of Collection classes.
	 * 
	 * @param arr
	 *            the array to print
	 */
	public static void printArray(char[] arr)
	{
		printArray(arr, "[", "]", ", ", false);
	}

	/**
	 * Prints out the array on one line with the specified left and right
	 * surrounding characters (such as [ and ]) and delimiter with no newline at
	 * end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param left
	 *            the left surrounding string
	 * @param right
	 *            the right surrounding string
	 * @param delim
	 *            delimiter between elements
	 */
	public static void printArray(char[] arr, String left, String right,
			String delim)
	{
		printArray(arr, left, right, delim, false);
	}

	/**
	 * Prints out the array on one line with default delimiters (,) surrouned by
	 * square brackets ([ and ]) with optional newline at end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param newline
	 *            whether to print a newline character at the end of the line
	 */
	public static void printArray(char[] arr, boolean newline)
	{
		printArray(arr, "[", "]", ", ", newline);
	}

	/**
	 * Prints out the array on one line with the specified left and right
	 * surrounding characters (such as [ and ]) and delimiter with optional
	 * newline at end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param left
	 *            the left surrounding string
	 * @param right
	 *            the right surrounding string
	 * @param delim
	 *            delimiter between elements
	 * @param newline
	 *            whether to print a newline character at the end of the line
	 */
	public static void printArray(char[] arr, String left, String right,
			String delim, boolean newline)
	{
		System.out.print(left);
		for (int i = 0; i < arr.length; i++)
		{
			System.out.print(arr[i]);
			if (i < arr.length - 1)
				System.out.print(delim);
		}
		System.out.print(right);
		if (newline)
			System.out.println();
	}

	/**
	 * Prints each element in the array on its own line, and end with a newline
	 * character
	 * 
	 * @param arr
	 *            the array to print
	 */
	public static void printlnArray(char[] arr)
	{
		printlnArray(arr, true);
	}

	/**
	 * Prints each element in the array on its own line, optionally ending with
	 * a newline character
	 * 
	 * @param arr
	 *            the array to print
	 * @param newline
	 *            whether to print a newline after the last element
	 */
	public static void printlnArray(char[] arr, boolean newline)
	{
		if (newline)
		{
			for (char e : arr)
			{
				System.out.println(e);
			}
		}
		else
		{
			for (int i = 0; i < arr.length; i++)
			{
				if (i < arr.length - 1)
					System.out.println(arr[i]);
				else
					System.out.print(arr[i]);
			}
		}
	}
	
	/**
	 * Prints out the array on one line with default delimiters (,) surrouned by
	 * square brackets ([ and ]) with no newline at end. This printing is
	 * analogous to the toString method of Collection classes.
	 * 
	 * @param arr
	 *            the array to print
	 */
	public static void printArray(boolean[] arr)
	{
		printArray(arr, "[", "]", ", ", false);
	}

	/**
	 * Prints out the array on one line with the specified left and right
	 * surrounding characters (such as [ and ]) and delimiter with no newline at
	 * end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param left
	 *            the left surrounding string
	 * @param right
	 *            the right surrounding string
	 * @param delim
	 *            delimiter between elements
	 */
	public static void printArray(boolean[] arr, String left, String right,
			String delim)
	{
		printArray(arr, left, right, delim, false);
	}

	/**
	 * Prints out the array on one line with default delimiters (,) surrouned by
	 * square brackets ([ and ]) with optional newline at end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param newline
	 *            whether to print a newline character at the end of the line
	 */
	public static void printArray(boolean[] arr, boolean newline)
	{
		printArray(arr, "[", "]", ", ", newline);
	}

	/**
	 * Prints out the array on one line with the specified left and right
	 * surrounding characters (such as [ and ]) and delimiter with optional
	 * newline at end.
	 * 
	 * @param arr
	 *            the array to print
	 * @param left
	 *            the left surrounding string
	 * @param right
	 *            the right surrounding string
	 * @param delim
	 *            delimiter between elements
	 * @param newline
	 *            whether to print a newline character at the end of the line
	 */
	public static void printArray(boolean[] arr, String left, String right,
			String delim, boolean newline)
	{
		System.out.print(left);
		for (int i = 0; i < arr.length; i++)
		{
			System.out.print(arr[i]);
			if (i < arr.length - 1)
				System.out.print(delim);
		}
		System.out.print(right);
		if (newline)
			System.out.println();
	}

	/**
	 * Prints each element in the array on its own line, and end with a newline
	 * character
	 * 
	 * @param arr
	 *            the array to print
	 */
	public static void printlnArray(boolean[] arr)
	{
		printlnArray(arr, true);
	}

	/**
	 * Prints each element in the array on its own line, optionally ending with
	 * a newline character
	 * 
	 * @param arr
	 *            the array to print
	 * @param newline
	 *            whether to print a newline after the last element
	 */
	public static void printlnArray(boolean[] arr, boolean newline)
	{
		if (newline)
		{
			for (boolean e : arr)
			{
				System.out.println(e);
			}
		}
		else
		{
			for (int i = 0; i < arr.length; i++)
			{
				if (i < arr.length - 1)
					System.out.println(arr[i]);
				else
					System.out.print(arr[i]);
			}
		}
	}

	/**
	 * Removes all trailing null elements from the end of the specified array and returns
	 * a new array starting from the first index through the last non-null index.
	 * Ignores all null elements that are followed, at some point, by a non-null
	 * element.  For example, for the following array:
	 * 
	 * [null, A, B, null, C, D, null, null, null], this method returns
	 * 
	 * [null, A, B, null, C, D].
	 * 
	 * If the specified array is null, then this method returns null.
	 * 
	 * @param arr the array to trim
	 * @return a new array with all trailing null elements removed
	 */
	public static <E> E[] trimArrayEnd(E[] arr)
	{
		if (arr == null) return null;
		if (arr.length == 0) return arr;
		
		int i = arr.length;
		
		for (; i > 0 && arr[i - 1] == null; i--) ;
		
		E[] arr2 = (E[])Array.newInstance(arr.getClass().getComponentType(), i);
		System.arraycopy(arr, 0, arr2, 0, i);
		
		return arr2;
	}
	
	/**
	 * Removes all leading null elements from the start of the specified array and returns
	 * a new array starting from the first non-null index through the last index.
	 * Ignores all null elements that are preceded, at some point, by a non-null
	 * element.  For example, for the following array:
	 * 
	 * [null, null, A, B, null, C, D, null, null], this method returns
	 * 
	 * [A, B, null, C, D, null, null].
	 * 
	 * If the specified array is null, then this method returns null.
	 * 
	 * @param arr the array to trim
	 * @return a new array with all leading null elements removed
	 */
	public static <E> E[] trimArrayStart(E[] arr)
	{
		if (arr == null) return null;
		if (arr.length == 0) return arr;
		
		int i = 0;
		
		for (; i < arr.length && arr[i] == null; i++) ;
		
		int newLength = arr.length - i;
		
		E[] arr2 = (E[])Array.newInstance(arr.getClass().getComponentType(), newLength);
		System.arraycopy(arr, i, arr2, 0, newLength);
		
		return arr2;
	}
	
	/**
	 * Removes all leading and trailing null elements from the start and end of
	 * the specified array and returns a new array starting from the first non-null
	 * index through the last non-null index.  Ignores all null elements that are
	 * preceded, at some point, and followed, at some point, by a non-null
	 * element.  For example, for the following array:
	 * 
	 * [null, null, A, B, null, C, D, null, null], this method returns
	 * 
	 * [A, B, null, C, D].
	 * 
	 * If the specified array is null, then this method returns null.
	 * 
	 * @param arr the array to trim
	 * @return a new array with all leading and trailing null elements removed
	 */
	public static <E> E[] trimArray(E[] arr)
	{
		if (arr == null) return null;
		if (arr.length == 0) return arr;
		
		int start = 0;
		for (; start < arr.length && arr[start] == null; start++) ;
		
		int end = arr.length;
		if (end != start) //equal if the entire array contains only nulls
		{
			for (; end > 0 && arr[end - 1] == null; end--) ;
		}
		
		System.out.println(start + ", " + end);
		
		int newLength = end - start;
		
		if (newLength < 0) newLength = 0;
		
		E[] arr2 = (E[])Array.newInstance(arr.getClass().getComponentType(), newLength);
		System.arraycopy(arr, start, arr2, 0, newLength);
		
		Character.isDigit('a');
		
		return arr2;
	}
	
}
